package com.tuniu.agents.common.util;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.web.multipart.MultipartFile;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FileProcessUtil {
    
    /**
     * Process image file and convert it to Base64 encoding
     * @param file Image file
     * @return Base64 encoded image string
     */
    public static String processImageFile(MultipartFile file) {
        try {
            byte[] imageBytes = file.getBytes();
            return Base64.getEncoder().encodeToString(imageBytes);
        } catch (IOException e) {
            log.error("Failed to process image file", e);
            throw new RuntimeException("Failed to process image file: " + e.getMessage());
        }
    }

    /**
     * Process PDF file and extract text content
     * @param file PDF file
     * @return Text content from PDF file
     */
    public static String processPdfFile(MultipartFile file) {
        try (PDDocument document = PDDocument.load(file.getBytes())) {
            PDFTextStripper stripper = new PDFTextStripper();
            return stripper.getText(document);
        } catch (IOException e) {
            log.error("Failed to process PDF file", e);
            throw new RuntimeException("Failed to process PDF file: " + e.getMessage());
        }
    }

    /**
     * Process Word document (.doc)
     * @param file Word document
     * @return Text content from document
     */
    public static String processDocFile(MultipartFile file) {
        try (HWPFDocument document = new HWPFDocument(file.getInputStream())) {
            WordExtractor extractor = new WordExtractor(document);
            return extractor.getText();
        } catch (IOException e) {
            log.error("Failed to process Word document (.doc)", e);
            throw new RuntimeException("Failed to process Word document (.doc): " + e.getMessage());
        }
    }

    /**
     * Process Word document (.docx)
     * @param file Word document
     * @return Text content from document
     */
    public static String processDocxFile(MultipartFile file) {
        try (XWPFDocument document = new XWPFDocument(file.getInputStream())) {
            XWPFWordExtractor extractor = new XWPFWordExtractor(document);
            return extractor.getText();
        } catch (IOException e) {
            log.error("Failed to process Word document (.docx)", e);
            throw new RuntimeException("Failed to process Word document (.docx): " + e.getMessage());
        }
    }

    /**
     * Process Excel file (.xls, .xlsx)
     * @param file Excel file
     * @return Text content from Excel file
     */
    public static String processExcelFile(MultipartFile file) {
        StringBuilder content = new StringBuilder();
        try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) {
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                Sheet sheet = workbook.getSheetAt(i);
                content.append("Sheet: ").append(sheet.getSheetName()).append("\n");
                
                for (Row row : sheet) {
                    for (Cell cell : row) {
                        switch (cell.getCellType()) {
                            case STRING:
                                content.append(cell.getStringCellValue()).append("\t");
                                break;
                            case NUMERIC:
                                content.append(cell.getNumericCellValue()).append("\t");
                                break;
                            case BOOLEAN:
                                content.append(cell.getBooleanCellValue()).append("\t");
                                break;
                            default:
                                content.append("\t");
                        }
                    }
                    content.append("\n");
                }
                content.append("\n");
            }
            return content.toString();
        } catch (IOException e) {
            log.error("Failed to process Excel file", e);
            throw new RuntimeException("Failed to process Excel file: " + e.getMessage());
        }
    }

    /**
     * Process text file
     * @param file Text file
     * @return Text content
     */
    public static String processTextFile(MultipartFile file) {
        try {
            return new String(file.getBytes(), StandardCharsets.UTF_8);
        } catch (IOException e) {
            log.error("Failed to process text file", e);
            throw new RuntimeException("Failed to process text file: " + e.getMessage());
        }
    }

    /**
     * Automatically select appropriate processing method based on file type
     * @param file Uploaded file
     * @return Processed file content
     */
    public static String processFile(MultipartFile file) {
        String contentType = file.getContentType();
        String fileName = file.getOriginalFilename();
        
        if (contentType != null) {
            if (contentType.startsWith("image/")) {
                // Process image file
                return processImageFile(file);
            } else if (contentType.equals("application/pdf")) {
                // Process PDF file
                return processPdfFile(file);
            } else if (contentType.equals("application/msword")) {
                // Process .doc file
                return processDocFile(file);
            } else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
                // Process .docx file
                return processDocxFile(file);
            } else if (contentType.equals("application/vnd.ms-excel") || 
                      contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
                // Process Excel file
                return processExcelFile(file);
            } else {
                // Process text file
                return processTextFile(file);
            }
        } else if (fileName != null) {
            // Determine by file extension
            String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
            switch (extension) {
                case "doc":
                    return processDocFile(file);
                case "docx":
                    return processDocxFile(file);
                case "xls":
                case "xlsx":
                    return processExcelFile(file);
                case "pdf":
                    return processPdfFile(file);
                case "jpg":
                case "jpeg":
                case "png":
                    return processImageFile(file);
                default:
                    return processTextFile(file);
            }
        } else {
            // Default to text file processing
            return processTextFile(file);
        }
    }
} 